package com.fh.shop.api.member.biz;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.fh.shop.api.common.ResponseEnum;
import com.fh.shop.api.common.ServerResponse;
import com.fh.shop.api.common.SystemConstant;
import com.fh.shop.api.member.mapper.IMemberMapper;
import com.fh.shop.api.member.param.MemberAddParam;
import com.fh.shop.api.member.param.MemberUpdatePasswordParam;
import com.fh.shop.api.member.po.Member;
import com.fh.shop.api.member.vo.MemberVo;
import com.fh.shop.api.mq.message.MailMessage;
import com.fh.shop.api.mq.producer.MailProducer;
import com.fh.shop.api.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.UUID;

@Service("memberService")
@Transactional(rollbackFor = Exception.class)
public class IMemberServiceImpl implements IMemberService {

    @Autowired
    private IMemberMapper memberMapper;
    @Autowired
    private MailUtil mailUtil;
    @Value("${server.url}")
    private String serverUrl;
    @Value("${mail.title}")
    private String mailTitle;
    @Autowired
    private MailProducer mailProducer;

    @Override
    public ServerResponse reg(MemberAddParam memberAddParam) {
        // ============验证
        // 非空验证
        // ""  "    "
        String memberName = memberAddParam.getMemberName();
        String confirmPassword = memberAddParam.getConfirmPassword();
        String password = memberAddParam.getPassword();
        String mail = memberAddParam.getMail();
        String phone = memberAddParam.getPhone();
        String nickName = memberAddParam.getNickName();
        String code = memberAddParam.getCode();
        if (StringUtils.isBlank(memberName)
                ||StringUtils.isBlank(password)
                ||StringUtils.isBlank(confirmPassword)
                ||StringUtils.isBlank(mail)
                ||StringUtils.isBlank(phone)
                ||StringUtils.isBlank(code)
                ||StringUtils.isBlank(nickName)) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_IS_NULL);
        }

        // 密码一致性验证
        if (!password.equals(confirmPassword)) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_PASSWORD_IS_ERROR);
        }

        // 手机号格式正确【java正则表达式】
        if (!ValidateUtil.isPhone(phone)) {
            return ServerResponse.error(ResponseEnum.PHONE_FORMAT_IS_ERROR);
        }
        // 邮箱格式正确【java正则表达式】
        if (!ValidateUtil.isMail(mail)) {
            return ServerResponse.error(ResponseEnum.MAIL_FORMAT_IS_ERROR);
        }
        // 判断 验证码是否正确
        // 从redis中取出对应的验证码
        String smsCode = RedisUtil.get(KeyUtil.buildSMSKey(phone));
        if (!code.equals(smsCode)) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_CODE_IS_ERROR);
        }
        // 会员名唯一性验证
        QueryWrapper<Member> memberNameQueryWrapper = new QueryWrapper<>();
        memberNameQueryWrapper.eq("memberName", memberName);
        Member member = memberMapper.selectOne(memberNameQueryWrapper);
        if (member != null) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_NAME_IS_EXIST);
        }
        // 电话唯一性验证
        QueryWrapper<Member> memberPhoneQueryWrapper = new QueryWrapper<>();
        memberPhoneQueryWrapper.eq("phone", phone);
        Member member1 = memberMapper.selectOne(memberPhoneQueryWrapper);
        if (member1 != null) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_PHONE_IS_EXIST);
        }
        // 邮箱唯一性验证
        QueryWrapper<Member> memberMailQueryWrapper = new QueryWrapper<>();
        memberMailQueryWrapper.eq("mail", mail);
        Member member2 = memberMapper.selectOne(memberMailQueryWrapper);
        if (member2 != null) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_MAIL_IS_EXIST);
        }
        // ============业务
        // 插入会员信息
        memberMapper.insert(memberAddParam);
        // 获取会员id
        Long id = memberAddParam.getId();
        // 发邮件[激活][问题：真正工作中，不会这么干，这么干导致性能低下！！！]
        String uuid = UUID.randomUUID().toString();
        // 同步发送
//        mailUtil.sendMail(mail, mailTitle, "<a href='"+serverUrl+"/api/members/active/"+uuid+"'>激活会员</a>");
        // 结合咱们的rabbitMQ实现异步发送
        // 组装消息
        MailMessage mailMessage = new MailMessage();
        mailMessage.setMail(mail);
        mailMessage.setTitle(mailTitle);
        mailMessage.setContent("<a href='"+serverUrl+"/api/members/active/"+uuid+"'>激活会员</a>");
        // 发送消息
        mailProducer.sendMailMessage(mailMessage);
        // redis key==value
        RedisUtil.setEx(KeyUtil.buildActiveMemberKey(uuid), id+"", SystemConstant.ACTIVE_MEMBER_EXPIRE);
        // 干啥？及时清空redis中不要的垃圾数据，释放空间
        RedisUtil.delete(KeyUtil.buildSMSKey(phone));
        return ServerResponse.success();
    }

    @Override
    @Transactional(readOnly = true)
    public ServerResponse login(String memberName, String password) {
        // 非空验证
        if (StringUtils.isBlank(memberName) || StringUtils.isBlank(password)) {
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_IS_NULL);
        }
        // 用户名验证
        QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("membername", memberName);
        // 查询数据库取出来的
        Member member = memberMapper.selectOne(memberQueryWrapper);
        if (member == null) {
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_NAME_IS_ERROR);
        }
        // 密码验证
        String dbPassword = member.getPassword();
        if (!password.equals(dbPassword)) {
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_PASSWORD_IS_ERROR);
        }
        // 激活状态验证
        if (member.getStatus().intValue() != SystemConstant.ACTIVE_MEMBER_STATUS) {
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_STATUS_IS_ERROR);
        }
        // 用户登录成功
        // 将会员信息响应给客户端 【坚决不能包含 密码 这种敏感信息】
        MemberVo memberVo = new MemberVo();
        Long id = member.getId();
        memberVo.setId(id);
        memberVo.setNickName(member.getNickName());
        // 通过uuid随机数，来保证每次登录，生成的token都是不一样的
        String uuid = UUID.randomUUID().toString();
        memberVo.setUuid(uuid);
        // memberVo转换为字符串 【json】【用户信息】
        String memberVoJson = JSON.toJSONString(memberVo);
        // 生成签名
        String sign = Md5Util.sign(memberVoJson, SystemConstant.SECRET);
        // 进行base64编码
        String memberVoJsonBase64 = Base64.getEncoder().encodeToString(memberVoJson.getBytes(StandardCharsets.UTF_8));
        // 组装token信息 x.y
        String token = memberVoJsonBase64 + "." + sign;
        // 在redis中存储一个标志位，设置过期时间2分钟
        RedisUtil.setEx(KeyUtil.buildMemberKey(id), uuid, SystemConstant.MEMBER_EXPIRE_TIME);
        return ServerResponse.success(token);
    }

    @Override
    public ServerResponse updatePassword(MemberUpdatePasswordParam memberUpdatePasswordParam, Long id) {
        // ==========验证
        // 非空验证
        String newPassword = memberUpdatePasswordParam.getNewPassword();
        String oldPassword = memberUpdatePasswordParam.getOldPassword();
        String confirmPassword = memberUpdatePasswordParam.getConfirmPassword();
        if (StringUtils.isBlank(newPassword)
                || StringUtils.isBlank(oldPassword)
                || StringUtils.isBlank(confirmPassword)) {
            return ServerResponse.error(ResponseEnum.MEMBER_UPDATE_PASSWORD_IS_NULL);
        }
        // 新密码和确认密码是否一致
        if (!newPassword.equals(confirmPassword)) {
            return ServerResponse.error(ResponseEnum.MEMBER_UPDATE_PASSWORD_IS_ERROR);
        }
        // 旧密码是否正确
        Member member = memberMapper.selectById(id);
        String dbPassword = member.getPassword();
        if (!oldPassword.equals(dbPassword)) {
            return ServerResponse.error(ResponseEnum.MEMBER_UPDATE_PASSWORD_OLD_PASSWORD_IS_ERROR);
        }
        // ==========业务
        // 更新密码
        Member member1 = new Member();
        member1.setId(id);
        member1.setPassword(newPassword);
        memberMapper.updateById(member1);
        // 删除redis中的key
        RedisUtil.delete(KeyUtil.buildMemberKey(id));
        return ServerResponse.success();
    }

    @Override
    public boolean activeMember(String uuid) {
        // 非空判断【路径传参，就不需要做非空判断，路径传参的参数必填的，如果不写，就进入不到接口中】

        // 从redis中取出对应的id
        String uuidKey = KeyUtil.buildActiveMemberKey(uuid);
        String memeberId = RedisUtil.get(uuidKey);
        // 判断是否存在 [几种情况下，memeberId == null]
        if (memeberId == null) {
            return false;
        }
        // 更新会员
        Member member = new Member();
        member.setId(Long.parseLong(memeberId));
        member.setStatus(SystemConstant.ACTIVE_MEMBER_STATUS);
        memberMapper.updateById(member);
        // 删除redis中的key
        RedisUtil.delete(uuidKey);
        return true;
    }

    @Override
    public ServerResponse sendMail(String mail) {
        // 非空验证
        if (StringUtils.isBlank(mail)) {
            return ServerResponse.error(ResponseEnum.MEMBER_ACTIVE_MAIL_IS_NULL);
        }
        // 邮箱格式验证
        if (!ValidateUtil.isMail(mail)) {
            return ServerResponse.error(ResponseEnum.MAIL_FORMAT_IS_ERROR);
        }
        // 邮箱必须在会员表中有对应的记录
        QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("mail", mail);
        Member member = memberMapper.selectOne(memberQueryWrapper);
        if (member == null) {
            return ServerResponse.error(ResponseEnum.MEMBER_ACTIVE_MAIL_IS_ERROR);
        }
        // 判断会员是否已经被激活了
        if (member.getStatus() == SystemConstant.ACTIVE_MEMBER_STATUS) {
            return ServerResponse.error(ResponseEnum.MEMBER_ACTIVE_IS_TRUE);
        }
        String uuid = UUID.randomUUID().toString();
        Long id = member.getId();
        // redis
        RedisUtil.setEx(KeyUtil.buildActiveMemberKey(uuid), id+"", SystemConstant.ACTIVE_MEMBER_EXPIRE);
        // 发送邮件
        mailUtil.sendMail(mail, mailTitle, "<a href='"+serverUrl+"/api/members/active/"+uuid+"'>激活会员</a>");
        return ServerResponse.success();
    }
}
